/**
 * 
 */
package jmine.tec.report.cell.impl;

import java.text.NumberFormat;
import java.util.List;

import jmine.tec.report.cell.DataCell;
import jmine.tec.report.cell.FormattedCell;
import jmine.tec.report.cell.FunctionDataCell;

/**
 * {@link FunctionDataCell} that combines double values from the child cells, preserving the type of the first child cell or using an
 * DoubleDataCell if the childCells are empty
 * 
 * @author takeshi
 */
public abstract class AbstractDoubleFunctionDataCell extends AbstractFunctionDataCell implements FunctionDataCell {

    /**
     * @param childCells the child cells
     * @return DataCell
     * @see br.com.maps.util.report.cell.FunctionDataCell#eval(java.util.List)
     */
    public DataCell eval(final List<? extends DataCell> childCells) {
        if (childCells.isEmpty()) {
            return new DoubleDataCell(0);
        }
        final double[] children = new double[childCells.size()];
        for (int i = 0; i < children.length; i++) {
            final Double double1 = childCells.get(i).toDouble();
            if (double1 != null) {
                children[i] = double1.doubleValue();
            }
        }
        double combined = this.combine(children);
        DataCell cell = childCells.get(0);
        if (cell instanceof CurrencyDataCell) {
            return new CurrencyDataCell(combined);
        } else if (cell instanceof PercentageDataCell) {
            return new PercentageDataCell(combined, this.findNumberFormat(childCells));
        } else {
            return new DoubleDataCell(combined, this.findNumberFormat(childCells));
        }
    }

    /**
     * Procura um {@link NumberFormat} para ser usado na celula de resultado
     * 
     * @param children {@link List} de {@link DataCell}
     * @return {@link NumberFormat}
     */
    private NumberFormat findNumberFormat(List<? extends DataCell> children) {
        NumberFormat nf = this.getNumberFormat();
        if (nf != null) {
            return nf;
        }
        for (DataCell dataCell : children) {
            if (dataCell instanceof FormattedCell && ((FormattedCell) dataCell).getNumberFormat() != null) {
                return ((FormattedCell) dataCell).getNumberFormat();
            }
        }
        return null;
    }

    /**
     * Combina os valores passados como double
     * 
     * @param values double[] valores
     * @return double
     */
    protected abstract double combine(double... values);

    /**
     * @return {@link NumberFormat}
     */
    protected NumberFormat getNumberFormat() {
        return null;
    }

}
